package com.control;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import jdbm.htree.HTree;

import com.access.Spider;
import com.data.Keyword;

public class KeywordManager {

	private HashMap<String, Keyword> keywords = new HashMap<String, Keyword>();
	private Spider spider = new Spider();
	private ArrayList<String> stopWords = new ArrayList<String>();
	private ArrayList<HashMap<String, Integer>> docTermFreqList = new ArrayList<HashMap<String, Integer>>();
	private Porter porter = new Porter();
	private String content = new String();

	// Data to be returned
	private ArrayList<Integer> docSize = new ArrayList<Integer>();
	private ArrayList<Integer> max_tf = new ArrayList<Integer>();
	private ArrayList<ArrayList<String>> wordsForDocs = new ArrayList<ArrayList<String>>();;

	public ArrayList<Integer> getDocSize() {
		return docSize;
	}

	public ArrayList<Integer> getMax_tf() {
		return max_tf;
	}

	public ArrayList<ArrayList<String>> getWordsForDocs() {
		return wordsForDocs;
	}

	public void indexKeywords(ArrayList<String> urls, JDBManager dbManager) {

		try {
			createStopWords();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

		for (int i = 0; i < urls.size(); i++)
			createKeywordForOneDoc(urls.get(i), i);

		calculateTermWeight();

		for (HashMap<String, Integer> docTermFreq : docTermFreqList) {
			ArrayList<String> words = new ArrayList<String>();
			for (String key : docTermFreq.keySet()) {
				words.add(key);
			}
			wordsForDocs.add(words);
		}

		HTree keywordTable;
		try {
			keywordTable = dbManager.loadHashTable("keywordTable");
			dbManager.buildHashTable(keywords, keywordTable);

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private void createKeywordForOneDoc(String url, int urlIndex) {
		content = spider.extractContent(url);

		String[] stringArray = content.split("[^a-zA-Z0-9]");
		ArrayList<String> stringArrayList = new ArrayList<String>();

		HashMap<String, Integer> docTermFreq = new HashMap<String, Integer>();
		int max = 0;

		for (String s : stringArray) {
			if (s.isEmpty() == false)
				stringArrayList.add(s);
		}
		docSize.add(stringArrayList.size());

		for (String s : stringArrayList) {
			String stemmer = porter.stripAffixes(s);
			if (stopWords.contains(stemmer) == false) {
				if (docTermFreq.containsKey(stemmer)) {
					docTermFreq.put(stemmer, docTermFreq.get(stemmer) + 1);
				} else
					docTermFreq.put(stemmer, 1);
			}
		}

		// Record the max_tf
		for (String key : docTermFreq.keySet()) {
			if (docTermFreq.get(key) > max)
				max = docTermFreq.get(key);
		}

		// Create the Keyword object
		for (String key : docTermFreq.keySet()) {
			Keyword keyword;
			if (keywords.containsKey(key)) {
				keywords.get(key).getDocs().add(urlIndex);
				keywords.get(key).getTermFreq().add(docTermFreq.get(key));
			} else {
				keyword = new Keyword(key);
				keyword.getDocs().add(urlIndex);
				keyword.getTermFreq().add(docTermFreq.get(key));
				keywords.put(key, keyword);
			}

		}

		max_tf.add(max);
		docTermFreqList.add(docTermFreq);

	}

	// Calculate the term weight
	private void calculateTermWeight() {
		int max = 0;
		int doc = 0;
		int tF = 0;
		float weight = 0;

		for (String key : keywords.keySet()) {
			Keyword keyword = keywords.get(key);
			int dF = keyword.getTermFreq().size();
			for (int i = 0; i < dF; i++) {
				doc = keyword.getDocs().get(i);
				tF = keyword.getTermFreq().get(i);
				max = max_tf.get(doc);
				weight = (float) ((tF * (Math.log((float) 30 / dF) / Math
						.log(2))) / max);
				keyword.getTermWeight().add(weight);
			}
		}
	}

	// Create the stopwords list.
	private void createStopWords() throws FileNotFoundException {
		java.io.File file = new java.io.File("stopwords.txt");
		java.util.Scanner input = new java.util.Scanner(file);

		while (input.hasNext()) {
			stopWords.add(input.next());
		}
		input.close();
	}

}
